package com.arron.jvm;

import java.util.concurrent.TimeUnit;

/**
 * @Classname JmmTest
 * @Description TODO
 * @Date 2020/8/18 20:07
 * @Created by 刘
 */

/**
 *  jmm 是一组抽象的规范，定义多线程如何访问jvm共享内存中的程序字段，变量等
 *      1.可见性
 *      2.原子性
 *      3.有序性
 *  volatile不保证原子性的原因：
 *      出现了丢失写值的情况
 *      addPlusPlus方法没有加锁，允许同时多个线程操作，因此多个线程在自己
 *      工作内存中改变了num值之后，准备写回主物理内存的时候，多个线程同时写就容易出现重复写
 *      因此运行结果总是少于20000
 */



public class JmmTest {

    public static void main(String[] args) {

        Resource resource = new Resource();

//        seeOkByVolatile(resource);
        System.out.println(Thread.activeCount());
        for (int i = 1; i <= 20; i++) {
            new Thread(()->{
                for (int j = 0; j < 1000; j++) {
                    resource.addPlusPlusPlus();
                }
            },String.valueOf(i)).start();
        }
        System.out.println(Thread.activeCount());
        //其他线程结束了就剩main线程和后台垃圾回收线程，此时Thread.activeCount()=2
        while (Thread.activeCount()>2){
            Thread.yield();
        }
        System.out.println(Thread.currentThread().getName()+" over num:"+resource.adder.sum());
    }

    /**
     * 保证jmm可见性
     * @param resource
     */
    private static void seeOkByVolatile(Resource resource) {
        new Thread(() -> {
            System.out.println("come in .......");
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            resource.changeNum();
            System.out.println(Thread.currentThread().getName() + " update num " + resource.num);
        }, "AAA").start();

        while (resource.num.intValue() == 0) {

        }
        System.out.println("over ===============");
    }

}
